﻿Imports System.Net
Imports System.Net.Sockets
Imports System.Text
Imports System.IO
Imports System.Globalization

Public Class NicoLiveCommentServer


    Private Client As TcpClient
    Private IsStarted As Boolean

#Region "Events"

    Public Event LiveProgramStarted As EventHandler(Of LiveProgramEventArgs)
    Protected Sub OnLiveProgramStarted(ByVal e As LiveProgramEventArgs)
        RaiseEvent LiveProgramStarted(Me, e)
    End Sub

    Public Event LiveProgramPreviewStart As EventHandler(Of PreviewLiveProgramEventArgs)
    Protected Sub OnLiveProgramPreviewStart(ByVal e As PreviewLiveProgramEventArgs)
        RaiseEvent LiveProgramPreviewStart(Me, e)
    End Sub

#End Region

    Public Sub Connect()
        IsStarted = True

        Dim thread = New Threading.Thread(AddressOf ReceiveStreamInfo)
        thread.Name = "NicoLiveCommentServer thread"
        thread.Start()
    End Sub

    Public Sub Disconnect()
        IsStarted = False
        If Client Is Nothing Then
            Exit Sub
        End If
        Try
            Client.Close()
            Client = Nothing
        Catch ex As Exception
        End Try
    End Sub

    Public Property UserAgent As String

    Private Function GetContent(ByVal uri As Uri) As String

        Dim request = DirectCast(WebRequest.Create(uri), HttpWebRequest)
        request.UserAgent = UserAgent

        Dim content As String = ""
        Using response = request.GetResponse
            Using reader = New System.IO.StreamReader(response.GetResponseStream, System.Text.Encoding.UTF8)
                content = reader.ReadToEnd
            End Using
        End Using

        Return content

    End Function

    Private Function GetAlertInfo() As AlertInfo
        Dim content = GetContent(New Uri("http://live.nicovideo.jp/api/getalertinfo"))
        Dim doc = XDocument.Parse(content)

        If doc.<getalertstatus>.@status.ToUpperInvariant <> "OK" Then
            ' TODO
        End If

        Dim info = New AlertInfo
        info.Address = doc.<getalertstatus>.<ms>.<addr>.Value
        info.Port = Convert.ToInt32(doc.<getalertstatus>.<ms>.<port>.Value)
        info.Thread = doc.<getalertstatus>.<ms>.<thread>.Value

        Return info
    End Function


    Private Sub ReceiveStreamInfo()
        Try
            Dim info As AlertInfo = Nothing
            Try
                info = GetAlertInfo()
                If info Is Nothing Then
                    ' TODO
                    Exit Sub
                End If

            Catch ex As Exception
#If DEBUG Then
                Stop
#End If
            End Try


            Client = New TcpClient(info.Address, info.Port)
            'Client.ReceiveTimeout = 

            Dim thread = String.Format("<thread thread=""{0}"" version=""20061206"" res_from=""-200""/>" & vbNullChar, info.Thread)
            Dim stream = Client.GetStream()

            Dim buffer = UTF8Encoding.UTF8.GetBytes(thread)
            stream.Write(buffer, 0, buffer.Length)
            stream.Flush()

            Using memoryStream = New MemoryStream()
                Do While IsStarted
                    Dim b As Integer = -1
                    Try
                        b = stream.ReadByte()
                    Catch ex As Exception
                        Exit Do
                    End Try

                    If b = 0 Then
                        memoryStream.Position = 0

                        Try
                            Dim text = System.Text.Encoding.UTF8.GetString(memoryStream.ToArray)
                            If text.StartsWith("<chat") Then
                                Dim doc = XDocument.Parse(text)
                                ParseCommentServerResponse(doc)
                            End If
                        Catch ex As Exception

                        End Try

                        memoryStream.SetLength(0)
                    ElseIf b = -1 Then
                        Exit Do
                    Else
                        memoryStream.WriteByte(Convert.ToByte(b))
                    End If
                Loop
            End Using

        Catch ex As Exception

        Finally
            Try
                If Client IsNot Nothing Then
                    Client.Close()
                    Client = Nothing
                End If
            Catch
            End Try
        End Try
    End Sub

    Private Sub ParseCommentServerResponse(ByVal document As XDocument)
        Try
            Dim values = document.<chat>.Value.Split(New Char() {","c}, StringSplitOptions.RemoveEmptyEntries)

            If values.Length < 3 Then
                Exit Sub
            End If

            Dim p = New LiveProgram
            p.Id = Convert.ToInt32(values(0))
            p.Station.Id = values(1)
            p.CasterId = Convert.ToInt32(values(2))
            p.IsOnAir = True
            p.CrawlingDateTime = Now
            OnLiveProgramPreviewStart(New PreviewLiveProgramEventArgs(p))

            Dim content = GetContent(New Uri("http://live.nicovideo.jp/api/getstreaminfo/lv" & p.Id.ToString(CultureInfo.InvariantCulture)))
            Dim doc = XDocument.Parse(content)

            If doc.<getstreaminfo>.@status.ToUpperInvariant <> "OK" Then
                Exit Sub
            End If

            p.Title = doc.<getstreaminfo>.<streaminfo>.<title>.Value
            p.Description = doc.<getstreaminfo>.<streaminfo>.<description>.Value
            p.Station.Name = doc.<getstreaminfo>.<communityinfo>.<name>.Value
            p.Station.IconUri = New Uri(doc.<getstreaminfo>.<communityinfo>.<thumbnail>.Value)

            OnLiveProgramStarted(New LiveProgramEventArgs(p))

        Catch ex As Exception

        End Try

    End Sub

End Class
